package visitor

import (
	"cuelang.org/go/cue/ast"
	"fmt"
	"gitee.com/runx/dm/pkg/visitor/types"
	"strings"
)

type TypeAttr struct {
	Name  string
	Type  string
	Value string
}
type TypeVisitor struct {
	Ref            bool
	field          *ast.Field
	name           string
	attrs          []*TypeAttr
	isType         bool
	maxAttrNameLen int
	maxAttrTypeLen int
}

func (v *TypeVisitor) visit() {
	v.visitName()
	v.visitAttrs()
}

func (v *TypeVisitor) visitAttrs() {
	vv := v.field.Value
	switch vv.(type) {
	case *ast.StructLit: //只处理模型定义
		vvv := vv.(*ast.StructLit)
		for i, _ := range vvv.Elts {
			v.attrs = append(v.attrs, v.visitAttr(vvv.Elts[i].(*ast.Field)))
		}
	}
}
func (v *TypeVisitor) visitAttr(attr *ast.Field) *TypeAttr {
	attrName := attr.Label.(*ast.Ident).Name
	nLen := len(attrName)
	if nLen > v.maxAttrNameLen {
		v.maxAttrNameLen = nLen
	}
	attrValue := types.Of(attr.Value).Value(v.Ref)

	nLen = len(attrValue)
	if nLen > v.maxAttrTypeLen {
		v.maxAttrTypeLen = nLen
	}
	return &TypeAttr{
		Name: attrName,
		Type: attrValue,
	}
}

func (v *TypeVisitor) visitName() {
	id := v.field.Label.(*ast.Ident)
	v.name = strings.TrimPrefix(id.Name, "#")
	v.isType = strings.HasPrefix(id.Name, "#")
}

func (v *TypeVisitor) write(ctx *strings.Builder) {
	ctx.WriteString(fmt.Sprintf("\ntype %s struct {\n", v.name))
	fortmat := fmt.Sprintf("-%d", v.maxAttrNameLen)
	fortmatV := fmt.Sprintf("-%d", v.maxAttrTypeLen)

	for _, vv := range v.attrs {
		ori := []byte(vv.Name)
		ori[0] = ori[0] - 32
		ctx.WriteString(fmt.Sprintf("    %"+fortmat+"s %"+fortmatV+"s `json:\"%s,omitempty\"`\n", string(ori), vv.Type, vv.Name))
	}
	ctx.WriteString("}\n")
}
